//
//  AudioSensor.m
//  Pennyworth
//
//  Created by Chris Karr on 5/21/08.
//  Copyright 2008 Chris Karr. All rights reserved.
//

#import "AudioSensor.h"
#import "Context.h"
#import "SensorsController.h"

#define SENSOR_NAME @"Audio Volume"

#define MONITOR_AUDIO @"Monitor_Audio"

@implementation AudioSensor

- (void) awakeFromNib
{
	[[SensorsController sharedController] addSensor:SENSOR_NAME];

	volume = 0.0;
	
	input = [[MTCoreAudioDevice defaultInputDevice] retain];
	
	[input setDelegate:self];
	[input setIOTarget:self 
		  withSelector:@selector(ioForDevice:timeStamp:inputData:inputTime:outputData:outputTime:clientData:) 
		withClientData:nil];
	
	[input deviceStart];
	
	started = YES;
	
	[[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(update:) userInfo:nil repeats:YES] retain];
}

- (void) update: (NSTimer *) theTimer
{
	if (![[SensorsController sharedController] canFire:SENSOR_NAME])
	{
		if (started)
		{
			[input deviceStop];
			started = NO;
		}

		NSMutableDictionary * note = [NSMutableDictionary dictionary];
		[note setValue:SENSOR_NAME forKey:OBSERVATION_SENSOR];
		[[NSNotificationCenter defaultCenter] postNotificationName:OBSERVATION_UPDATE object:self userInfo:note];
		
		return;
	}
	else
	{
		if (!started)
		{
			[input deviceStart];
			started = YES;
		}
	}
	
	NSMutableDictionary * note = [NSMutableDictionary dictionary];
		
	[note setValue:SENSOR_NAME forKey:OBSERVATION_SENSOR];
	[note setValue:[NSNumber numberWithInteger:((NSInteger) volume * 10)] forKey:OBSERVATION_OBSERVATION];
	[note setValue:[NSNumber numberWithInteger:5] forKey:OBSERVATION_LIFESPAN];
	[[NSNotificationCenter defaultCenter] postNotificationName:OBSERVATION_UPDATE object:self userInfo:note];
}

- (void) audioDeviceStartDidFail:(MTCoreAudioDevice *) theDevice forReason:(OSStatus) theReason
{
	NSLog (@"error 0x%x", theReason);
}

- (OSStatus) ioForDevice:(MTCoreAudioDevice *) theDevice 
			   timeStamp:(const AudioTimeStamp *) inNow 
			   inputData:(const AudioBufferList *) inInputData 
			   inputTime:(const AudioTimeStamp *) inInputTime 
			  outputData:(AudioBufferList *) outOutputData 
			  outputTime:(const AudioTimeStamp *) inOutputTime 
			  clientData:(void *) inClientData
{
	unsigned count = inInputData->mBuffers[0].mDataByteSize;
	
	unsigned size = sizeof (volume);
	
	float sampleRate = 100;
	
	float myVolume = 0.0;
	
	float * data = inInputData->mBuffers[0].mData;
	
	unsigned i = 0;
	for (i = 0; i < count / size; i++)
		myVolume += fabsf (data[i]);

	volume = ((volume * (sampleRate - 1)) + (20 * log10f (myVolume / (count / size)))) / sampleRate;
	
	return noErr;
}
@end
